//
//  ChivoxEngine.m
//  ChivoxEngine
//
//  Created by John on 2018/8/24.
//  Copyright © 2018年 Chivox. All rights reserved.
//

#import "ChivoxEngineHeader.h"
#import "ChivoxTaskQue.h"
#import "ChivoxService/ChivoxService.h"

#define _ON_INIT_SUCCESS() {\
if ([self._listener respondsToSelector:@selector(onInitSuccess:)]) {\
[self._listener onInitSuccess:self];\
} else {\
    /* TODO: log error*/\
}\
}

#define _ON_INIT_FAIL(_errId, _errMsg) {\
if ([self._listener respondsToSelector:@selector(onInitFail:errId:errMsg:)]) {\
[self._listener onInitFail:self errId:_errId errMsg:_errMsg];\
} else {\
/* TODO: log error*/\
}\
}

#define _ON_START_SUCCESS(_token) {\
if ([self._listener respondsToSelector:@selector(onStartSuccess:token:)]) {\
[self._listener onStartSuccess:self token:_token];\
} else {\
    /*TODO: log error */\
}\
}

#define _ON_START_FAIL(_errId, _errMsg) {\
if ([self._listener respondsToSelector:@selector(onStartFail:errId:errMsg:)]) {\
[self._listener onStartFail:self errId:_errId errMsg:_errMsg];\
} else {\
    /* TODO: log error */\
}\
}

#define _ON_STOP_SUCCESS(_token) {\
if ([self._listener respondsToSelector:@selector(onStopSucess:token:)]) {\
[self._listener onStopSucess:self token:_token];\
} else {\
    /*TODO: log error */\
}\
}

#define _ON_STOP_FAIL(_token, _errId, _errMsg) {\
if ([self._listener respondsToSelector:@selector(onStopFail:token:errId:errMsg:)]) {\
[self._listener onStopFail:self token:_token errId:_errId errMsg:_errMsg];\
} else {\
    /* TODO: log error */\
}\
}

#define _ON_RESULT_TEXT(_token, _text) {\
if ([self._listener respondsToSelector:@selector(onResult:token:text:)]) {\
[self._listener onResult:self token:_token text:_text];\
} else {\
    /* TODO: log error */\
}\
}

#define _ON_RESULT_BIN(_token, _bin) {\
if ([self._listener respondsToSelector:@selector(onResult:token:bin:)]) {\
[self._listener onResult:self token:_token bin:_bin];\
} else {\
/* TODO: log error */\
}\
}

#define CHIVOX_ENGINE_STATUS_NONE 0
#define CHIVOX_ENGINE_STATUS_INITING 1
#define CHIVOX_ENGINE_STATUS_INITED 2
#define CHIVOX_ENGINE_STATUS_START 3
#define CHIVOX_ENGINE_STATUS_FEED 4
#define CHIVOX_ENGINE_STATUS_STOP 5
#define CHIVOX_ENGINE_STATUS_CANCELING 6

@interface ChivoxEngine()
@property (atomic, assign) int _status;
@property (nonatomic, weak) id<ChivoxEngineListener> _listener;
@property (nonatomic, strong) ChivoxTaskQue *_taskQue;
@property (nonatomic, strong) NSString *_currentToken;
@end

@implementation ChivoxEngine
{
}

- (id)init {
    if (self = [super init]) {
        self._status = CHIVOX_ENGINE_STATUS_NONE;
        self._currentToken = NULL;
        self._listener = NULL;
        self._taskQue = [[ChivoxTaskQue alloc] init];
        if (self._taskQue) {
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                [self._taskQue loop];
            });
        }
    }
    return self;
}

+ (id)create:(id<ChivoxEngineListener>)listener {
    ChivoxEngine *engine = [[ChivoxEngine alloc] init];
    if (engine) {
        engine._listener = listener;
        engine._taskQue.engineListener = listener;
    }
    return engine;
}

- (void)initCloud:(NSString *)cfg {
    if (self._status != CHIVOX_ENGINE_STATUS_NONE) {
        // TODO: errcode and log
        _ON_INIT_FAIL(60001, @"the engine is initing or has been inited");
        return;
    }
    self._status = CHIVOX_ENGINE_STATUS_INITING;
    
    // TODO: 改成后台执行
    
    ChivoxService *innerEngine = [ChivoxService create:@"ws" :nil];
    if (!innerEngine) {
        // TODO: errcode and log
        self._status = CHIVOX_ENGINE_STATUS_NONE;
        _ON_INIT_FAIL(60001, @"create inner cloud engine failed");
        return;
    }
    
    [innerEngine load:@{}];
    /*
    NSMutableString *errMsg = [[NSMutableString alloc] init];
    int errId = [innerEngine load:cfg];
    if (errId != 0) {
        self._status = CHIVOX_ENGINE_STATUS_NONE;
        _ON_INIT_FAIL(errId, errMsg);
        return;
    }
     */
    
    self._taskQue.innerEngine = innerEngine;
    self._status = CHIVOX_ENGINE_STATUS_INITED;
    _ON_INIT_SUCCESS();
}

- (void)initNative:(NSString *)cfg {
    if (self._status != CHIVOX_ENGINE_STATUS_NONE) {
        // TODO: errcode and log
        _ON_INIT_FAIL(60001, @"the engine is initing or has been inited");
        return;
    }
    self._status = CHIVOX_ENGINE_STATUS_INITING;
    
    // TODO: 改成后台执行
    
    ChivoxService *innerEngine = [ChivoxService create:@"native" :nil];
    if (!innerEngine) {
        // TODO: errcode and log
        self._status = CHIVOX_ENGINE_STATUS_NONE;
        _ON_INIT_FAIL(60001, @"create inner native engine failed");
        return;
    }
    
    /*
    NSMutableString *errMsg = [[NSMutableString alloc] init];
    int errId = [innerEngine load:cfg errMsg:errMsg];
    if (errId != 0) {
        self._status = CHIVOX_ENGINE_STATUS_NONE;
        _ON_INIT_FAIL(errId, errMsg);
        return;
    }
     */
    [innerEngine load:@{}];
    
    self._taskQue.innerEngine = innerEngine;
    self._status = CHIVOX_ENGINE_STATUS_INITED;
    _ON_INIT_SUCCESS();
}

- (void)start:(NSString *)param {
    if (self._status < CHIVOX_ENGINE_STATUS_INITED) {
        // TODO: errcode and log
        _ON_START_FAIL(60001, @"start fail, engine has not been inited");
        return;
    }
    if (self._status != CHIVOX_ENGINE_STATUS_INITED || self._status != CHIVOX_ENGINE_STATUS_STOP) {
        // TODO: errcode and log
        _ON_START_FAIL(60001, @"start fail, call `start` in wrong order");
        return;
    }
    self._status = CHIVOX_ENGINE_STATUS_START;
    
    self._currentToken = [self genToken];
    
    ChivoxTask *task = [[ChivoxTask alloc] init];
    task.token = self._currentToken;
    [self._taskQue appendTask:task];
    
    ChivoxTaskMsg *connMsg = [[ChivoxTaskMsg alloc] init:CHIVOX_TASK_MSG_CONNECT withText:param];
    ChivoxTaskMsg *startMsg = [[ChivoxTaskMsg alloc] init:CHIVOX_TASK_MSG_START withText:param];
    [task appendMsg:connMsg];
    [task appendMsg:startMsg];
    
    _ON_START_SUCCESS(self._currentToken);
}

- (void)feed:(NSData *)data {
    if (!data || data.length == 0) {
        return;
    }
    
    if (self._status != CHIVOX_ENGINE_STATUS_START || self._status != CHIVOX_ENGINE_STATUS_FEED) {
        // TODO: errcode and log
        //[self._listener onFeedFail:self token:NULL errId:60001 errMsg:@"feed fail, call `feed` in wrong order"];
        return;
    }
    
    self._status = CHIVOX_ENGINE_STATUS_FEED;
    
    ChivoxTask *last = [self._taskQue lastTask];
    if (!last || ![last.token isEqualToString:self._currentToken]) {
        // 任务已结束
        // TODO: log warning
        return;
    }
    
    ChivoxTaskMsg *feedMsg = [[ChivoxTaskMsg alloc] init:CHIVOX_TASK_MSG_FEED withBin:data];
    [last appendMsg:feedMsg];
}

- (void)stop {
    if (self._status != CHIVOX_ENGINE_STATUS_START || self._status != CHIVOX_ENGINE_STATUS_FEED) {
        // TODO: errcode and logerr
        //[self._listener onStopFail:self token:self._currentToken errId:60001 errMsg:@"stop fail, call `stop` in wrong order"];
        return;
    }
    
    self._status = CHIVOX_ENGINE_STATUS_STOP;

    ChivoxTask *last = [self._taskQue lastTask];
    if (!last) {
        // TODO: log warning
        // 任务已结束
        return;
    }
    
    ChivoxTaskMsg *stopMsg = [[ChivoxTaskMsg alloc] init:CHIIVOX_TASK_MSG_STOP withText:NULL];
    [last appendMsg:stopMsg];
}

- (NSString *)genToken {
    // TODO: gen token
    return @"123456";
}


@end
